package gu.sql2java.manager.config.spring;

import java.lang.reflect.Method;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import gu.sql2java.config.RuntimeConfig;

/**
 * HTTP请求拦截器，实现在HTTP请求解析之前为请求方法安装sql2java运行时配置对象，方法调用结束删除
 * @author guyadong
 * @since 3.32.6
 */
@Configuration
public class RuntimeConfigInterceptor implements AsyncHandlerInterceptor,WebMvcConfigurer{
	private final String contextPath;
	public RuntimeConfigInterceptor(@Autowired(required = false) ServletContext servletContext) {
		/** 
		 * 当不启动WEB服务时 servletContext为null,
		 * 比如启动Spring应用时，SpringApplication.webApplicationType字段被设置为NONE:
		 * springApplication.setWebApplicationType(WebApplicationType.NONE)
		 * 此时拦截器是无效的 
		 */
		this.contextPath = null == servletContext ? null : servletContext.getContextPath();
	}
	
	/**
	 * 判断目标是否需要拦截
	 * @param request 
	 * @param handler 
	 */
	private boolean needIntercept(HttpServletRequest request, Object handler) {
		return null != contextPath && contextPath.equals(request.getContextPath()) && (handler instanceof HandlerMethod);
	}
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		if(needIntercept(request, handler)) {
			Method method = ((HandlerMethod)handler).getMethod();
			RuntimeConfig.installConfigOf(method);
		}
		return true;
	}
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		RuntimeConfig.removeLocalConfig();
	}
	@Override
	public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		/**
		 * 当WEB请求为异步请求时，不会调用afterCompletion，需要实现此方法才能清理thread-local 变量
		 * 参见 org.springframework.web.servlet.DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response)方法实现代码
		 * */
		afterCompletion(request, response, handler,null);
	}
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(this)
				.addPathPatterns("/**")  /** 添加拦截路径 */
				.excludePathPatterns("/error","/swagger-resources/**","/swagger/**", "/swagger2/**");/** 排除的拦截路径（此路径不拦截 */
	}

}
